﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Speech.Synthesis;
using System.Media;
using System.Xml;
using System.IO;



namespace ZpivajiciPocitac
{
    public partial class Form1 : Form
    {
        private SpeechSynthesizer _SS = new SpeechSynthesizer();
        private PromptBuilder pb = new PromptBuilder();

        public Form1()
        {
            InitializeComponent();
            
            _SS.Volume = 80;
            _SS.Rate = 0;
        }


        //play SSML--------------------------------------------------------------------------------------
        private void play_ssml()
        {
            pb.ClearContent();
            pb.AppendSsmlMarkup(textBox2.Text);
            _SS.SpeakAsync(pb);
        }


        //play music xml----------------------------------------------------------------------------------
        private void play_musicxml()
        {
            XmlDocument xmlDoc1 = new XmlDocument();
            xmlDoc1.LoadXml(textBox1.Text);

            //get important nodes
            XmlNodeList itemNodes = xmlDoc1.GetElementsByTagName("pitch");
            if (itemNodes.Count > 0)
            {
                foreach (XmlElement pitch in itemNodes)
                {
                    //get step & octave
                    XmlNodeList stepNodes = pitch.GetElementsByTagName("step");
                    XmlNodeList octaveNodes = pitch.GetElementsByTagName("octave");
                    foreach (XmlElement step in stepNodes)
                    {
                        int octave = -1;
                        foreach (XmlElement octaveNode in octaveNodes)
                        {
                            octave = Int32.Parse(octaveNode.InnerText);
                        }

                        if (octave != -1)
                        {
                            //get duration
                            double duration = Double.Parse(pitch.NextSibling.InnerText);

                            //transform string note to int note
                            string note = step.InnerText;
                            int noteInt = -1;
                            switch (note)
                            {
                                case "C": noteInt = 1; break;
                                case "D": noteInt = 2; break;
                                case "E": noteInt = 3; break;
                                case "F": noteInt = 4; break;
                                case "G": noteInt = 5; break;
                                case "A": noteInt = 6; break;
                                case "B": 
                                case "H": noteInt = 7; break;
                                default: break;
                            }

                            //here we should have note, octave & duration
                            int frequency = getFrequency(octave,noteInt);
                                
                            //play it
                            if(frequency > 32 && frequency < 32000)
                                Console.Beep(frequency, (int)(duration * 220));
                        }
                    }
                }
            }
        }


        //get frequency based on f(x) = 440 * (1.059463..)^x = 523.3 Hz ...x is number of halfsteps from middle C (c4)
        private int getFrequency(int octave, int note) {
            int x = ((octave - 1)* 7) + note;
            const int c = 22; //middle c
            int d = x - c;

            int f = (int)(440 * Math.Pow(1.059463, d * 2));
            return f;
        }




        //load MUSIC XML file
        private void button3_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            //openFileDialog1.InitialDirectory = "c:\\";
            openFileDialog1.Filter = "MusicXML soubor (*.xml)|*.xml|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                string file = openFileDialog1.FileName;
                textBox1.Text = File.ReadAllText(file);
            }
        }

        //load SSML file
        private void button4_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            //openFileDialog1.InitialDirectory = "c:\\";
            openFileDialog1.Filter = "SSML soubor (*.ssml)|*.ssml|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                string file = openFileDialog1.FileName;
                textBox2.Text = File.ReadAllText(file);
            }
        }


        //some buttons
        private void button1_Click(object sender, EventArgs e)
        {
            play_musicxml();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            play_ssml();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            play_ssml();
            play_musicxml();
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            _SS.Volume = trackBar1.Value;
        }

        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            _SS.Rate = trackBar2.Value;
        }
    }
}
